/*
    Copyright (C) 2013  Letian Yi  <letian0805@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CHAT_H_
#define _CHAT_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <syslog.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <assert.h>
#include "main.h"
#include "configsym.h"

#define MAXLINK 100
#define MAXMSG 300
#define MAXLEN 1024
#define MAXWAIT 50
#define MAXEVENTS 1000
#define MAXNUM 30

#define SERV_NAME "SERVER"

#define SAFE_FREE(mem) \
do{ \
    if(mem){ \
        free(mem); \
        mem = NULL; \
    } \
}while(0)

static inline char *name(char *s, int len)
{
    char *ss = malloc(len);
    assert(ss);
    strncpy(ss,s,len-1);
    ss[len-1] = 0;
    return ss;
}

extern char  * menu1[];
typedef enum{
    HEAD_START = 0,
    HEAD_TO,
    HEAD_FROM,
    HEAD_MSG,
    HEAD_TIME,
    HEAD_FDBK,
    HEAD_END,
    HEAD_LAST,
}HeadType;

#define CMD_WHOISON_STR "1CWS:"
typedef enum{
    CMD_LOGIN,
    CMD_WHOISON,
    CMD_LOGOUT,
    CMD_GETIELIST,
    CMD_LAST,
}ServerCmd;

typedef enum{
    PKT_IDLE,
    PKT_READ,
    PKT_WRITE,
    PKT_RDFULL,
    PKT_WRFULL,
    PKT_OTHER,
}PktStatus;

typedef struct{
    char *to;
    char *from;
    char *time;
    int nmsg;
    int curmsg;
    char *msg[MAXMSG];
    char *fdbk;
}ChatPacket;

typedef struct _ChatList ChatList;
struct _ChatList{
    void *data;
    ChatList *next;
    ChatList *prev;
};

typedef struct{
    char *name;
    int flag;
    int status;
    int events;
    int sktfd;
    int epfd;
    ChatPacket *pktsnd;
    ChatPacket *pktget;
    PktStatus pktstat;
    socklen_t sktlen;
    struct sockaddr_in sktaddr;
}ChatClient;

typedef struct{
    int maxwait;
    int port;
    ChatList *cli_list;
    int sktfd;
    int epfd;
    pthread_t pid;
    pthread_mutex_t lock;
}ChatServer;

int chat_add_events(ChatClient *cli, int events);

int chat_remove_events(ChatClient *cli);

int fd_add_events(int epfd, int fd, int events);

int fd_remove_events(int epfd, int fd);

char *str_strip(char *str);

int line_parse(char *line, char tok, char **key, char **val);

int socket_readline(int sktfd, char *buf);

int socket_writeline(int sktfd, char *line, int len);

ChatPacket *packet_new(const char *from, const char *to);

int packet_add_msg(ChatPacket *pkt, const char *msg);

HeadType packet_head_parse(const char *line);

char *packet_head_getdata(HeadType type, char *head);

char *packet_make_head(HeadType type, const char *data);

int client_login(ChatClient *cli);

int client_parse_input(ChatClient *cli, char *input,char **name);

int client_parse_head(ChatClient *cli, char *head);

int client_flush(ChatClient *cli);

int packet_free(ChatPacket *pkt);

int socket_send_head(int sktfd, HeadType type, const char *data);

ServerCmd server_parse_cmd(char *msg);

int send_to_client(ChatClient *cli, const char *msg);

char *gettime(void);
#endif
